/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
 *                                                                           *
 *                          Copyright (c) 2010                               *
 *                  Alen Stojanov [ ioi.alen@gmail.com ]                     *
 *                Jacobs University Bremen, Bremen, Germany                  *
 *                                                                           *
 *                          All Rights Reserved.                             *
 *                                                                           *
 *    Permission to use, copy, modify and distribute this software and       *
 *    its documentation is hereby granted, provided that both the            *
 *    copyright notice and this permission notice appear in all copies of    *
 *    the software, derivative works or modified versions, and any           *
 *    portions thereof, and that both notices appear in supporting           *
 *    documentation.                                                         *
 *                                                                           *
 *    This code is distributed in the hope that it will be useful, but       *
 *    WITHOUT ANY WARRANTY; without even the implied warranty of             *
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. THE AUTHORS       *
 *    DISCLAIM ANY LIABILITY OF ANY KIND FOR ANY DAMAGES WHATSOEVER          *
 *    RESULTING FROM THE USE OF THIS SOFTWARE.                               *
 *                                                                           *
 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */

#ifndef GLSINGLEPREVIEW_H_
#define GLSINGLEPREVIEW_H_

#include <QGLWidget>
#include <QMutex>
#include <QWheelEvent>

#include "tsdata.h"
#include "lsp.h"

/**
 * @class GLLSPGraph
 * @author Alen Stojanov, October 2010
 *
 * @brief Creat LSP projection of the data
 *
 * This class is used to represent the rendered data in an LSP
 * projection, as well as to fascilitate interactivity with the
 * selection of the data points in the TSView
 */
class GLLSPGraph : public QGLWidget
{
	Q_OBJECT

public:
	/**
	 * @brief Default constructor
	 */
	GLLSPGraph(QWidget *parent = 0);
	/**
	 * @brief Remove the particular TS of the preview graph
	 * @param data Pointer to the TS data being removed
	 */
	void removeSeries(TSData *data);

public slots:
	/**
	 * @brief Add a particular TS to the preview graph
	 *
	 * This function will include the data into the graph, and will
	 * repaint the graph such that the new TS is included
	 *
	 * @param data Pointer to the new TS data being added
	 */
	void on_addSeries(QVector<TSData*> data);
	/**
	 * @brief Update the range in the Mantra.
	 * @param rangeMinX	Minumum coordinate of the X-axis
	 * @param rangeMaxX	Maximum coordinate of the X-axis
	 */
	void on_updateRange (double rangeMinX, double rangeMaxX);

	void on_updateControlPointsSize(int controlPointsSize);

protected:
	/**
	 * @brief Overloaded method to initialize the OpenGL widget
	 */
	void initializeGL();
	/**
	 * @brief Overloaded method to repaint the OpenGL widget
	 */
	void paintGL();
	/**
	 * @brief Overloaded method to resize the OpenGL widget
	 * @param width 	The width of the viewport
	 * @param height 	The height of the viewort
	 */
	void resizeGL(int width, int height);
	/**
	 * @brief Overload the Mouse press event to detect the last mouse position
	 * @param event 	The default mouse event
	 */
	void mousePressEvent(QMouseEvent *event);
	/**
	 * @brief Overload the Mouse move event
	 * @param event		The default mouse event
	 */
	void mouseMoveEvent(QMouseEvent *event);
	/**
	 * @brief Overload the Mouse release event
	 * @param event		The default mouse event
	 */
	void mouseReleaseEvent (QMouseEvent * event);
	/**
	 * @brief Overload the Mouse wheel event
	 * @param event		The default mouse wheel event
	 */
	void wheelEvent (QWheelEvent *event);

private:
	/**
	 * @brief Use a mutex for concurency
	 *
	 * Ensure that when the data is being updated, repaint on the scene has not been
	 * performed (this process might take a long time in certain situations)
	 */
	QMutex mutex;
	/**
	 * @brief Store all the data into one single vector of TSData
	 */
	QVector<TSData*> data;

	/**
	 * @brief Store the LSP projected data into vector of TSPoints
	 */
	QVector<TSPoint> projection;
	/**
	 *	@brief Store the connections between each projection point
	 *
	 *	This vector has the same size as the projection vector, and
	 *	each connection[i] express connection between point 'i' and
	 *	point 'connection[i]'. Since every point pertains to a
	 *	particular cluster, we can safely assume that each point has
	 *	exactly one connection to its medoid.
	 */
	QVector<int> connections;
	/**
	 * Stores convex hull of the right click selection of the object
	 */
	QVector<TSPoint> convex_hull;

	/**
	 * Ensure that the range has been set, and the graph has been initialized
	 */
	 bool isInitialized;
	/**
	 * Define the margin size on the mantra view
	 */
	double marginSize;


	double dataRadius;
	double zoom;

	double rangeMinX;
	double rangeMaxX;
	double rangeMinY;
	double rangeMaxY;

	double centerX;
	double centerY;

	double scale;

	/**
	 * Grab the last position of the mouse on a press event
	 */
	QPoint lastPos;
	/**
	 * A hull which is formed during the mouse right click events
	 */
	QVector<TSPoint> hull;

	double minX;
	double maxX;
	double minY;
	double maxY;

	/**
	 * @brief Determine whether a point is inside a polygon or not
	 */
	bool isInsidePolygon(QVector<TSPoint> &polygon, TSPoint &p);

signals:
	void selectTSData(QVector<TSData*> series);

public:
	/**
	 * Default destructor
	 */
	~GLLSPGraph();
};

#endif /* GLSINGLEPREVIEW_H_ */
